package org.jetlinks.pro.datasource;

import reactor.core.Disposable;

import javax.annotation.Nonnull;

/**
 * 统一数据源接口定义,{@link DataSource#getType()}标识数据源类型.
 * <p>
 * 数据源统一管理,请勿手动调用{@link DataSource#dispose()}
 *
 * @author zhouhao
 * @since 1.10
 */
public interface DataSource extends Disposable {

    /**
     * @return 数据源ID
     */
    String getId();

    /**
     * @return 数据源类型
     */
    DataSourceType getType();

    /**
     * 执行指令,具体指令有对应的数据源实现定义.如果不支持则抛出{@link UnsupportedOperationException}.
     *
     * @param command 指令
     * @param <R>     结果类型
     * @return void
     * @see UnsupportedOperationException
     */
    @Nonnull
    <R> R execute(@Nonnull Command<R> command);

    /**
     * 判断数据源是为指定的类型
     *
     * @param target 类型
     * @return 是否为指定的类型
     */
    default boolean isWrapperFor(java.lang.Class<?> target) {
        return target.isInstance(this);
    }

    /**
     * 按指定类型拆箱数据源,返回对应的数据源。如果类型不一致,可能抛出{@link ClassCastException}
     *
     * @param target 目标类型
     * @param <T>    T
     * @return 数据源
     */
    default <T extends DataSource> T unwrap(Class<T> target) {
        return target.cast(this);
    }

}
